package com.shield.framework.security.token.jwt;

import com.shield.framework.config.ShieldConstant;
import com.shield.framework.config.ShieldSecurityProperties;
import com.shield.framework.security.auth.AuthUser;
import com.shield.framework.security.token.ShieldTokenService;
import io.jsonwebtoken.*;
import lombok.RequiredArgsConstructor;
import net.dreamlu.mica.core.utils.Charsets;
import net.dreamlu.mica.core.utils.DateUtil;
import net.dreamlu.mica.core.utils.StringUtil;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.context.annotation.Configuration;

import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.security.Key;
import java.time.Duration;
import java.util.Date;

/**
 * @description:
 * @Author Andy
 */
@RequiredArgsConstructor
/*@Configuration(proxyBeanMethods = false)*/
public class ShieldJwtTokenService implements ShieldTokenService,SmartInitializingSingleton {

    private final ShieldSecurityProperties properties;
    private JwtParser jwtParser;

    @Override
    public void afterSingletonsInstantiated() {
        //所以Bean 初始化完成以后 Spring IOC容器回调
        // jwt token 配置信息
        ShieldSecurityProperties.JwtToken jwtToken = properties.getJwtToken();
        String secret = jwtToken.getSecret();
        SignatureAlgorithm algorithm = jwtToken.getSignatureAlgorithm();
        // 加密 key
        Key keySpec = new SecretKeySpec(secret.getBytes(Charsets.UTF_8), algorithm.getJcaName());
        // jwtParser
        jwtParser = Jwts.parserBuilder()
                .setSigningKey(keySpec)
                .build();
    }

    /**
     * 获取用户身份信息
     *
     * @return 用户信息
     */
    public String getSubject(String token) {
        if (StringUtil.isBlank(token)) {
            return null;
        }
        // 注意此处 有几个异常需要处理
        Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);
        Claims body = claimsJws.getBody();
        if (body == null) {
            return null;
        }
        return body.getSubject();
    }

    /**
     * 创建令牌
     *
     * @param authUser   AuthUser
     * @param now        当前时间
     * @param expireTime 有效期
     * @return 令牌
     */
    public String createToken(AuthUser authUser, Date now, Duration expireTime) {
        // jwt token 配置信息
        ShieldSecurityProperties.JwtToken jwtToken = properties.getJwtToken();
        String secret = jwtToken.getSecret();
        SignatureAlgorithm algorithm = jwtToken.getSignatureAlgorithm();
        // 加密 key
        Key keySpec = new SecretKeySpec(secret.getBytes(Charsets.UTF_8), algorithm.getJcaName());
        return Jwts.builder()
                .setId(StringUtil.getUUID())
                .setAudience(jwtToken.getAudience())
                .setIssuer(jwtToken.getIssuer())
                .setIssuedAt(now)
                .setSubject(authUser.getUsername())
                .setNotBefore(now)
                .setExpiration(DateUtil.plus(now, expireTime))
                .signWith(keySpec, algorithm)
                .compact();
    }


}
